package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 李旭
 * @date 2021/11/30 15:07
 * @Description:
 */
@SuppressWarnings("all")
@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    //仓库的地址
    @Value("${ware.url}")
    private String wareUrl;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private RabbitService rabbitService;

    //校验库存
    @Override
    public boolean checkStock(OrderDetail orderDetail) {
        //Http请求 库存系统 （仓库系统）
        //Apach公司开发的HttpClient
        return "1".equals(HttpClientUtil.doGet(
                wareUrl + "/hasStock?skuId="+orderDetail.getSkuId()
                        +"&num=" + orderDetail.getSkuNum()));
    }

    //保存订单 及订单 详情
    @Override
    public Long insertOrder(OrderInfo orderInfo) {
        //1、保存订单表
        //1.2:订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //1.3:订单交易编码    提交订单之后 去支付宝 唯一主键
        String outTradeNo = "atguigu" + System.currentTimeMillis() +
                new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //1.4:订单描述  提交订单之后 去支付宝
        StringBuilder tradeBody = new StringBuilder();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        orderDetailList.forEach(orderDetail -> {
            tradeBody.append(orderDetail.getSkuName() + " ");
            //最新实时价格
            BigDecimal price = productFeignClient.getPrice(orderDetail.getSkuId());
            orderDetail.setOrderPrice(price);
        });
        if(tradeBody.length() > 100){
            orderInfo.setTradeBody(tradeBody.substring(0,100));
        }else{
            orderInfo.setTradeBody(tradeBody.toString());
        }
        //1.5:创建时间
        Calendar calendar = Calendar.getInstance();
        //当前时间  添加时间
        orderInfo.setCreateTime(calendar.getTime());
        //1.6失效时间  2小时 还不给钱 失效了
        calendar.add(Calendar.HOUR,2);
        orderInfo.setExpireTime(calendar.getTime());
        //1.7:进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //1.1:总金额
        orderInfo.sumTotalAmount();
        //保存订单表
        orderInfoMapper.insert(orderInfo);
        //2、订单详情表
        List<OrderDetail> orderDetails = orderInfo.getOrderDetailList();
        orderDetails.forEach(orderDetail -> {
            //将上面订单的主键设置到详情表的外键位置
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        });

        //TODO 4：删除购物车中已经购买了商品    二处： Redis|DB  同学们完成一下

        //5:计时开始  2小时之后 如果用户还没有给钱  就取消订单
 /*       rabbitService.sendDelayedMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL
          ,MqConst.ROUTING_ORDER_CANCEL,orderInfo.getId(),MqConst.DELAY_TIME);*/
        return orderInfo.getId();
    }

    //取消订单时   更新订单状态
    @Override
    public void updateOrderInfoStatus(String orderId) {
        //防止幂等性问题
        //  1: 防止重复提交
        //  2: 防止更新状态错误   未支付状态的订单才能关闭  已支付的状态不能关闭
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if(null != orderInfo && orderInfo.getProcessStatus().equals(ProcessStatus.UNPAID.name())){
            orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
            orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
            orderInfo.setExpireTime(new Date());
            orderInfoMapper.updateById(orderInfo);
        }

    }
    //根据订单的ID 查询订单对象
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        return orderInfoMapper.selectById(orderId);
    }


    /// 通用的    更新订单状态
    @Override
    public void updateOrderStatus(String orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfo.setId(Long.parseLong(orderId));
        orderInfoMapper.updateById(orderInfo);

    }

    //获取订单数据及订单详情集合
    public OrderInfo getOrderInfoAndDetails(Long orderId){
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(new QueryWrapper<OrderDetail>()
                .eq("order_id", orderId));
        orderInfo.setOrderDetailList(orderDetailList);
        return orderInfo;
    }
    //初始化 组合 库存系统所需要的数据  下面方法完成
    @Override
    public Map initWareData(OrderInfo orderInfo) {
        Map map = new HashMap<>();
        map.put("orderId", orderInfo.getId());
        map.put("consignee", orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay", "ONLINE".equals(orderInfo.getPaymentWay())?"2":"1");
        map.put("wareId", orderInfo.getWareId());//仓库的编号
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        List<Map>  listMap = orderDetailList.stream().map(orderDetail -> {
            Map m = new HashMap();
            m.put("skuId",orderDetail.getSkuId());
            m.put("skuNum",orderDetail.getSkuNum());
            m.put("skuName",orderDetail.getSkuName());
            return m;
        }).collect(Collectors.toList());
        map.put("details", listMap);
        return map;
    }
    //初始化 组合 库存系统所需要的数据  下面方法完成
    @Override
    public Map initWareData(String orderId) {
        //1:查询订单及订单详情
        OrderInfo orderInfo = getOrderInfoAndDetails(Long.parseLong(orderId));
       return initWareData(orderInfo);
    }

    //开始拆单    逻辑开发
    @Override
    public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {

        //wareSkuMap :  仓库编号与商品的对照关系
        //[
        //  {"wareId":"1","skuIds":["5","9"]}  Map1
        //  ,{"wareId":"2","skuIds":["1","10"]}Map2
        //  ]
        //原始订单
        OrderInfo originOrderInfo = getOrderInfoAndDetails(orderId);

        List<Map> wareSkuMapList = JSONObject.parseArray(wareSkuMap, Map.class);
        //返回值
        List<OrderInfo> subOrderInfoList = new ArrayList<>();

        for (Map wareSku : wareSkuMapList) {
            //子订单
            OrderInfo subOrderInfo = new OrderInfo();
            //父订单的大多数数据复制过来
            BeanUtils.copyProperties(originOrderInfo,subOrderInfo);//全部复制
            //设置子订单的父订单ID
            subOrderInfo.setParentOrderId(originOrderInfo.getId());
            //将子订单的ID 设置成null  后面保存时自动生成订单ID
            subOrderInfo.setId(null);
            //仓库的编号
            subOrderInfo.setWareId(String.valueOf(wareSku.get("wareId")));

            //原始订单详情集合
            List<OrderDetail> originOrderDetailList = originOrderInfo.getOrderDetailList();
            //子订单详情集合
            List<OrderDetail> subOrderDetailList = originOrderDetailList.stream().filter(originOrderDetail -> {
                //[
                //  {"wareId":"1","skuIds":["5","9"]}  Map1
                //  ,{"wareId":"2","skuIds":["1","10"]}Map2
                //  ]
                List<String> skuIds = (List<String>) wareSku.get("skuIds");
                for (String skuId : skuIds) {
                    if (originOrderDetail.getSkuId().toString().equals(skuId)) {
                        //存在 要
                        return true;
                    }
                }
                return false;
            }).collect(Collectors.toList());

            // 将子订单详情集合设置到子订单中
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //总金额
            subOrderInfo.sumTotalAmount();
            //保存子订单
            orderInfoMapper.insert(subOrderInfo);
            subOrderDetailList.forEach(subOrderDetail -> {
                //设置子订单主表的外键
                subOrderDetail.setOrderId(subOrderInfo.getId());
                orderDetailMapper.updateById(subOrderDetail);
            });

            subOrderInfoList.add(subOrderInfo);
        }
        //设置父订单的状态为订单已拆单
        updateOrderStatus(String.valueOf(orderId),ProcessStatus.SPLIT);
        return subOrderInfoList;
    }




}
